package utils

import (
	"encoding/json"
	"fmt"
	"reflect"
)

// JsonStr data转成 json 字符串
// 若 data 为 nil 则返回 "null"
// 若发生错误则返回 ""
func JsonStr(data any) string {
	if data == nil {
		return "null"
	}
	if bytes, err := json.Marshal(data); err == nil {
		return string(bytes)
	}
	return ""
}

// JsonBytes data转成 json 字节数组
// 若 data 为 nil 则返回 "null"字节数组
// 若发生错误则返回 nil
func JsonBytes(data any) []byte {
	if data == nil {
		return []byte("null")
	}
	if bytes, err := json.Marshal(data); err == nil {
		return bytes
	}
	return nil
}

// ToMap 结构体转为Map[string]interface{}
func ToMap(in interface{}) (map[string]interface{}, error) {
	out := make(map[string]interface{})

	v := reflect.ValueOf(in)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	if v.Kind() != reflect.Struct { // 非结构体返回错误提示
		return nil, fmt.Errorf("ToMap only accepts struct or struct pointer; got %T", v)
	}

	t := v.Type()
	// 遍历结构体字段
	// 指定tagName值为map中key;字段值为map中value
	for i := 0; i < v.NumField(); i++ {
		fi := t.Field(i)
		if tagValue := fi.Tag.Get("json"); tagValue != "" {
			out[tagValue] = v.Field(i).Interface()
		}
	}
	return out, nil
}

// SplitSlice 将data拆分为子slice最大长度为size的多维slice
// size 需不小于1，否则返回 nil
//
// 如:
//
//	data=[1,2,3,4,5,6,7], size=3
//
// 得到:
//
//	[[1,2,3],[4,5,6],[7]]
func SplitSlice(data []any, size int) [][]any {
	if size < 1 {
		return nil
	}
	l := len(data) / size
	if len(data)%size > 0 {
		l++
	}
	result := make([][]any, 0, l)
	for i := 0; i < l; i++ {
		s := i * size
		t := s + size
		if t > len(data) {
			t = len(data)
		}
		sub := make([]any, t-s)
		copy(sub, data[s:t])
		result = append(result, sub)
	}
	return result
}
